package com.hrm.websocket;

import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;

import cn.test.protocol.ProtocolImpl;

import com.hrm.service.PeopleService;

public class WebSocketServer extends Thread {
	private static final Log log = LogFactory.getLog(WebSocketSession.class);
	private Selector selector;
	static Queue<WebSocketSession> connectedSession;
	private static boolean started = false;
	private ServerSocketChannel sSChannel;
	private ServerSocket sSocket;
	@Autowired
	private ProtocolImpl protocolImpl;
	public ProtocolImpl getProtocolImpl() {
		return protocolImpl;
	}

	public void setProtocolImpl(ProtocolImpl protocolImpl) {
		this.protocolImpl = protocolImpl;
	}

	public WebSocketServer() {
		super(" ----- WebSocketServerThread");
		connectedSession = new ConcurrentLinkedQueue<WebSocketSession>();
	}

	public void run() {
		try {
			started=true;
			startServer();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void stopServer() {
		log.info("WebSocketServer is be closeing ......");
		started = false;
		try {
			selector.close();
			sSocket.close();
			sSChannel.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println("webSocket sever closed.");
		connectedSession=null;
	}

	public void startServer() throws IOException {
		sSChannel = ServerSocketChannel.open();
		sSChannel.configureBlocking(false);
		selector = Selector.open();
		sSocket = sSChannel.socket();
		sSocket.setReuseAddress(false);
//		sSocket.setSoTimeout(600000);//10分钟
		sSocket.bind(new InetSocketAddress(8192));
		sSChannel.register(selector, SelectionKey.OP_ACCEPT);
		log.info("web socket server started!");
		while (started) {
			int selectNum = selector.select();
			if (selectNum < 1) {
				return;
			}

			Iterator<SelectionKey> it = selector.selectedKeys().iterator();
			while (it.hasNext()) {
				SelectionKey key = it.next();
				if (key.isAcceptable()) {
					acceptSession(key);
				} else if (key.isReadable()) {
					readSession(key);
				}
				it.remove();
			}
		}
		System.out.println("webSocket sever over.");
	}

	public void acceptSession(SelectionKey key) throws IOException {
		ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key
				.channel();
		SocketChannel socketChannel = serverSocketChannel.accept();
		socketChannel.configureBlocking(false);
		socketChannel.register(selector, SelectionKey.OP_READ);

		WebSocketSession session = new WebSocketSession(socketChannel,protocolImpl);
		log.info("accept a web shell session ");
		connectedSession.add(session);
	}

	public void readSession(SelectionKey key) {
		SocketChannel socketChannel = (SocketChannel) key.channel();
		WebSocketSession session = findSession(socketChannel);
		if (!session.read()) {
			if(session.getUploadedSize()>0&&session.getUploadedSize()<session.getUploadFileSize()){
				//如果是取消文件上传的socket，则删除上传的临时文件
				if(session.getFilePath()!=null&&!"".equals(session.getFilePath())){//上传文件已存在
					log.info("upload cancel,delete the tmp file="+session.getFilePath());
					File file = new File(session.getFilePath());
					if(file.exists()){
						file.delete();
					}
				}
				
			}
			session.close();
			connectedSession.remove(session);
			log.info("session closed ");
		}
	}

	public WebSocketSession findSession(SocketChannel channel) {
		if (connectedSession == null || connectedSession.size() == 0) {
			return null;
		}
		for (WebSocketSession session : connectedSession) {
			if (session.socketChannel.equals(channel)) {
				return session;
			}
		}
		return null;
	}
	
	public static WebSocketSession findSessionByPid(String pid) {
		if (connectedSession == null || connectedSession.size() == 0) {
			return null;
		}
		if(pid==null||"".equals(pid.trim())){
			return null;
		}
		for (WebSocketSession session : connectedSession) {
			if (pid.equals(session.getPid())) {
				return session;
			}
		}
		return null;
	}
	
}
